第 3 步 - 长按以放置别针

使用长按操纵器可以使用户在 Kanzi 应用程序中长按节点。 这样可以让应用程序在用户于节点上按下指针并按住您的长按操纵器中设定的时长时做出响应。

在这一步中,您将使用长按操纵器,使用户通过长按地图将别针放置在地图上。例如,这样可以让用户标记地图上感兴趣的点。

放置别针

在本节中,您将创建和使用长按操纵器,在用户长按地图时放置别针到地图上。

要放置别针:

  1. onProjectLoaded() 函数中,在获取 Map 节点后以及创建输入操纵器之前,将 Pin 预设件实例化为 Map 节点的子节点:
        virtual void onProjectLoaded() KZ_OVERRIDE
        {
            ...
    
            //获取显示别针图标的预设件模板 Pin 引用。
            ResourceManager* resourceManager = getDomain()->getResourceManager();
            PrefabTemplateSharedPtr pinPrefabTemplate = resourceManager->acquireResource<PrefabTemplate>("kzb://pan_zoom_tap/Prefabs/Pin");
    
            //实例化 Pin 预设件。
            m_pin = pinPrefabTemplate->instantiate<Node2D>("Pin");
    
            //为 Map 节点添加您创建的 Pin 预设件实例。
            mapNode->addChild(m_pin);
    
            //禁用 Pin 预设件实例的可见性 (Visible) 属性。
            //在用户放置别针时启用可见性 (Visible) 属性。
            m_pin->setVisible(false);
    
            ...
        }
    
    private: 
    
        ...
    
        //为 Pin 预设件实例定义成员变量。
        Node2DSharedPtr m_pin;
    };
    
  2. PanZoomTap 类的私有部分定义长按消息的处理程序:
        //为 LongPressManipulator::LongPressMessage 消息定义处理程序,该消息来自 
        //具有可生成长按消息的输入操纵器的节点。
        void onLongPress(LongPressManipulator::LongPressMessageArguments& messageArguments)
        {
            //从消息参数获取用户长按的节点。
            Node2DSharedPtr mapNode = dynamic_pointer_cast<Node2D>(messageArguments.getSource());
    
            //获取用户长按的点。
            Vector2 pointerPosition = messageArguments.getPoint();
    
            //创建包含变换到用户长按的点的渲染变换。
            SRTValue2D pinSRT = SRTValue2D::createTranslation(pointerPosition);
    
            //定位用户长按的别针的尖端。
            pinSRT.setTranslation(pinSRT.getTranslation() - Vector2(m_pin->getActualWidth() * 0.5f, m_pin->getActualHeight() * 0.8f));
    
            //应用变换到 Pin 预设件实例。
            m_pin->setRenderTransformation(pinSRT);
    
            //启用 Pin 预设件实例的可见性 (Visible) 属性。
            m_pin->setVisible(true);
        }
  3. onProjectLoaded() 函数中创建 LongPressManipulator 操纵器并订阅 Map 节点的消息:
        virtual void onProjectLoaded() KZ_OVERRIDE
        {
            ...
    
            //创建生成长按消息的输入操纵器。
            LongPressManipulatorSharedPtr longPressManipulator = LongPressManipulator::create(domain);
    
            //添加输入操纵器到Map 节点。
            mapNode->addInputManipulator(longPressManipulator);
    
            //将长按持续时间设为 400 ms。长按操纵器会在用户按下节点持续
            //此时间量时识别该手势。
            //默认持续时间为 500 ms。
            longPressManipulator->setPressDuration(chrono::milliseconds(400));
    
            //订阅 Map 节点的 LongPressManipulator::LongPressMessage 消息。
            // LongPressManipulator 操纵器在用户按下该节点
            //获取您在 LongPressManipulator::setPressDuration 函数中设置的毫秒数时生成此消息。
            mapNode->addMessageHandler(LongPressManipulator::LongPressMessage, bind(&PanZoomTap::onLongPress, this, placeholders::_1));
        }
    
  4. 构建和运行应用程序。
    在应用程序中长按地图的任意位置,以放置别针。

保持放置别针的大小和方向

当用户缩放和旋转地图时,放置的别针随地图改变大小和旋转。这是因为您实例化了 Pin 预设件,它将别针作为 Map 节点的子节点。在本节中,将添加代码保持别针的大小和方向恒定。

要保持放置别针的大小和方向:

  1. PanZoomTap 类的私有部分创建函数,根据 Map 节点的比例和旋转更新已放置别针的比例和旋转:
        //更新 Pin 预设件实例的比例和旋转。
        void updatePinScaleAndRotation(SRTValue2D mapSRT, SRTValue2D pinSRT)
        {
            //将旋转设置为和 Map 节点旋转相反。
            pinSRT.setRotation(-mapSRT.getRotation());
    
            //将比例设置为和 Map 节点的比例相反。
            pinSRT.setScale(componentWiseDivide(Vector2(1.0f, 1.0f), mapSRT.getScale()));
    
            //应用渲染变换到 Pin 预设件实例。
            m_pin->setRenderTransformation(pinSRT);
        }
  2. 在上一节添加的 onLongPress 函数中,首先获取 Map 节点的渲染变换,然后调用 updatePinScaleAndRotation 函数。
    这样即可保持 Pin 的大小和方向相同,无论 Map 节点的缩放水平和旋转如何。
    替换 (Replace)
            //应用该变换到别针预设件实例。
            m_pin->setRenderTransformation(pinSRT);
            //获取 Map 节点的渲染变换 (Render Transformation) 属性。
            SRTValue2D mapSRT = mapNode->getRenderTransformation();
    
            //更新 Pin 预设件实例的比例和位置。
            updatePinScaleAndRotation(mapSRT, pinSRT);
    
  3. 在本教程第 2 步创建的 onPinchMoved 函数末尾,当用户缩放和旋转地图时更新已放置别针的比例和旋转:
        void onPinchMoved(PinchManipulator::MovedMessageArguments& messageArguments)
        {
            ...
    
            //获取 Pin 预设件实例的 渲染变换 (Render Transformation) 属性。
            SRTValue2D pinSRT = m_pin->getRenderTransformation();
    
            //更新 Pin 预设件实例的比例和位置。
            updatePinScaleAndRotation(mapWorldSRT, pinSRT);
        }
  4. 在本教程第 2 步创建的 onNodeDoubleTapped 函数末尾,当用户双敲地图时重置已放置别针的比例和旋转:
        void onNodeDoubleTapped(MultiClickManipulator::MultiClickMessageArguments& messageArguments)
        {
            ...
    
            //重置 Pin 预设件实例的旋转和比例。
            SRTValue2D pinSRT = m_pin->getRenderTransformation();
            pinSRT = SRTValue2D(Vector2(1.0f, 1.0f), 0, pinSRT.getTranslation());
            m_pin->setRenderTransformation(pinSRT);
        }
  5. 构建应用程序并将其部署到 Android 设备。
    在缩放和旋转地图时,放置的别针保持原有大小和方向。


< 上一步

接下来该做什么?

在本教程中,您已了解如何使用Kanzi 输入操纵器进行平移、缩放、旋转、重置位置以及在地图上放置别针。现在您可以:

另请参阅

要详细了解长按操纵器,请参阅使用长按操纵器

要了解如何将 Kanzi 应用程序部署到不同的平台,请参阅部署 Kanzi 应用程序